package controllers

import (
	"errmsg"
	"errors"
	"fmt"
	"github.com/astaxie/beego/logs"
	"github.com/astaxie/beego/validation"
	"io/ioutil"
	"net/url"
	"smart_home/api/bots"
	_ "smart_home/api/bots/cloud"
	"smart_home/api/models"
	"time"
	"tools"
)

type BotController struct {
	BaseController
}

// @title 登陆
// @param platform string true 来源平台
// @router /login/:platform [post]
func (c *BotController) Login() {
	var (
		mobile   int64
		password string
		state    string
		platform string
		user     *models.User
		err      error
	)

	// 头信息
	c.Ctx.Output.Header("Content-type", "text/html;charset=utf-8")
	c.Ctx.Output.Header("Access-Control-Allow-Origin", "*")
	c.Ctx.Output.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, token")
	c.Ctx.Output.Header("Access-Control-Allow-Methods", "GET,POST,PATCH,PUT,OPTIONS,DELETE")

	// 绑定数据
	c.Ctx.Input.Bind(&mobile, "mobile")
	c.Ctx.Input.Bind(&password, "password")
	c.Ctx.Input.Bind(&state, "state")
	c.Ctx.Input.Bind(&platform, ":platform")

	vali := validation.Validation{}
	vali.Required(mobile, "mobile").Message("手机号码不能为空")
	vali.Mobile(mobile, "mobile").Message("手机号码不正确")
	vali.Required(password, "password").Message("密码不能为空")
	vali.Required(state, "state").Message("state不能为空")
	if vali.HasErrors() {
		logs.Debug(vali.Errors)
		c.Error(vali.Errors[0])
		return
	}

	if user, err = models.GetUserByMobile(mobile); err != nil {
		c.Error(errmsg.ErrResponseFail)
		return
	}
	if user == nil {
		c.Error(errmsg.ErrResponseNotFound)
		return
	}

	if tools.MD5Encode(password) != user.Password {
		c.Error(errors.New("密码错误"))
		return
	}

	if state, err = url.PathUnescape(state); err != nil {
		c.Error(err)
		return
	}

	if err = bots.SetToken(state, user.Id, platform); err != nil {
		c.Error(err)
		return
	}

	c.Success(nil)
}

// @title 获取token
// @router /token/:platform [post]
func (c *BotController) Token() {
	var (
		platform      string
		grant_type    string
		client_id     string
		client_secret string
		code          string
		refresh_token string
		err           error
		msg           = "授权失败"
	)

	// 绑定数据
	c.Ctx.Input.Bind(&platform, ":platform")
	c.Ctx.Input.Bind(&grant_type, "grant_type")
	c.Ctx.Input.Bind(&client_id, "client_id")
	c.Ctx.Input.Bind(&client_secret, "client_secret")
	c.Ctx.Input.Bind(&code, "code")
	c.Ctx.Input.Bind(&refresh_token, "refresh_token")

	logs.Debug(c.Input())

	vali := validation.Validation{}
	vali.Required(client_id, "client_id")
	vali.Required(client_secret, "client_secret")
	if vali.HasErrors() {
		logs.Debug("vali err:", vali.Errors)
		goto Fail
	}

	if client_id != "bot" || client_secret != "123456" {
		goto Fail
	}

	if len(code) == 0 && len(refresh_token) == 0 {
		goto Fail
	}

	logs.Debug("input:", c.Input())

	// 验证token
	if len(code) > 0 {
		tk := bots.GetToken(code, platform)
		logs.Debug("tk:", tk)
		if len(tk) == 0 {
			goto Fail
		}

		// 添加refresh_token
		refresh_token = tools.GUUID()
		if err := bots.SetToken(refresh_token, code, platform, 365*24*time.Hour); err != nil {
			goto Fail
		}
	} else {
		// 刷新token
		code, refresh_token, err = bots.RefreshToken(refresh_token, platform)
		if err != nil {
			goto Fail
		}
	}

	c.Ctx.Output.Context.WriteString(fmt.Sprintf(`{"access_token":"%s", "refresh_token":"%s", "expires_in":%d}`, code, refresh_token, 1*24*60*60))
	return

Fail:
	str := fmt.Sprintf(`{"error":"403", "error_description":"%s"}`, msg)
	logs.Debug("err:", str, platform)
	c.Ctx.Output.Context.WriteString(str)
}

// @title 命令
// @router /command/:platform [post]
func (c *BotController) Command() {
	var (
		platform string
		body     []byte
		err      error
		bot      bots.BotInterface
	)

	c.Ctx.Input.Bind(&platform, ":platform")
	body, err = ioutil.ReadAll(c.Ctx.Request.Body)
	if err != nil {
		logs.Error("command err:", err)
		return
	}

	if bot = bots.GetBotInterface(platform); bot == nil {
		return
	}
	logs.Debug(string(body))
	bot.SetPlatform(platform)
	bot.SetBody(body)
	bot.Init()
	c.Data["json"] = bot.GetAnswer()
	logs.Debug("json:", c.Data["json"])
	c.ServeJSON()
}

// @title 隐私政策
// @router /privacy/:platform [get]
func (c *BotController) Privacy() {
	logs.Debug("privacy:", c.Input())
}
